filechooser: Make get_files return a list model
authorMatthias Clasen <mclasen@redhat.com>
Thu, 9 Jul 2020 05:29:20 +0000 (01:29 -0400)
committerMatthias Clasen <mclasen@redhat.com>
Thu, 9 Jul 2020 05:29:20 +0000 (01:29 -0400)
Like the other list getters in this interface,
make gtk_file_chooser_get_files() return a
list model.

gtk/gtkfilechooser.c
gtk/gtkfilechooser.h
gtk/gtkfilechooserbutton.c
gtk/gtkfilechooserdialog.c
gtk/gtkfilechoosernative.c
gtk/gtkfilechooserprivate.h
gtk/gtkfilechooserutils.c
gtk/gtkfilechooserwidget.c
tests/testfilechooser.c
tests/testgtk.c

index b77652bd1cc85dc6f0ee10da01f1f8d1ad3924d5..ff70023af90e50f262f236d307b452722f4bb8c6 100644 (file)
@@ -508,16 +508,15 @@ gtk_file_chooser_unselect_file (GtkFileChooser *chooser,
 /**
  * gtk_file_chooser_get_files:
  * @chooser: a #GtkFileChooser
- * 
- * Lists all the selected files and subfolders in the current folder of @chooser
- * as #GFile.
  *
- * Returns: (element-type GFile) (transfer full): a list
- *   containing a #GFile for each selected file and subfolder in the
- *   current folder.  Free the returned list with g_slist_free(), and
- *   the files with g_object_unref().
- **/
-GSList *
+ * Lists all the selected files and subfolders in the current folder
+ * of @chooser as #GFile.
+ *
+ * Returns: (transfer full): a list model containing a #GFile for each
+ *     selected file and subfolder in the current folder. Free the returned
+ *     list with g_object_unref().
+ */
+GListModel *
 gtk_file_chooser_get_files (GtkFileChooser *chooser)
 {
   g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL);
@@ -597,19 +596,15 @@ gtk_file_chooser_set_file (GtkFileChooser  *chooser,
 GFile *
 gtk_file_chooser_get_file (GtkFileChooser *chooser)
 {
-  GSList *list;
+  GListModel *list;
   GFile *result = NULL;
-  
+
   g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL);
 
   list = gtk_file_chooser_get_files (chooser);
-  if (list)
-    {
-      result = list->data;
-      list = g_slist_delete_link (list, list);
-
-      g_slist_free_full (list, g_object_unref);
-    }
+  if (g_list_model_get_n_items (list) > 0)
+    result = g_list_model_get_item (list, 0);
+  g_object_unref (list);
 
   return result;
 }
index b3b5aec9b889d66df12615393a4d18d0fc33d8c2..9fd20da3c93b32e0acd707b9dfd0cd8307281956 100644 (file)
@@ -123,7 +123,7 @@ gboolean             gtk_file_chooser_set_file            (GtkFileChooser
                                                            GFile                *file,
                                                            GError              **error);
 GDK_AVAILABLE_IN_ALL
-GSList *             gtk_file_chooser_get_files           (GtkFileChooser       *chooser);
+GListModel *         gtk_file_chooser_get_files           (GtkFileChooser       *chooser);
 GDK_AVAILABLE_IN_ALL
 gboolean             gtk_file_chooser_set_current_folder  (GtkFileChooser       *chooser,
                                                            GFile                *file,
index 97bd4eab903c0bb1cc7320ac1e04a3faaa5ae76e..c8d24fdb338a874f3312d2e90afb4586d371e552 100644 (file)
@@ -244,7 +244,7 @@ static gboolean gtk_file_chooser_button_select_file (GtkFileChooser *chooser,
 static void gtk_file_chooser_button_unselect_file (GtkFileChooser *chooser,
                                                   GFile          *file);
 static void gtk_file_chooser_button_unselect_all (GtkFileChooser *chooser);
-static GSList *gtk_file_chooser_button_get_files (GtkFileChooser *chooser);
+static GListModel *gtk_file_chooser_button_get_files (GtkFileChooser *chooser);
 static gboolean gtk_file_chooser_button_add_shortcut_folder     (GtkFileChooser      *chooser,
                                                                 GFile               *file,
                                                                 GError             **error);
@@ -750,17 +750,23 @@ get_selected_file (GtkFileChooserButton *button)
     return NULL;
 }
 
-static GSList *
+static GListModel *
 gtk_file_chooser_button_get_files (GtkFileChooser *chooser)
 {
   GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (chooser);
   GFile *file;
+  GListStore *store;
+
+  store = g_list_store_new (G_TYPE_FILE);
 
   file = get_selected_file (button);
   if (file)
-    return g_slist_prepend (NULL, file);
-  else
-    return NULL;
+    {
+      g_list_store_append (store, file);
+      g_object_unref (file);
+    }
+
+  return G_LIST_MODEL (store);
 }
 
 static gboolean
index 46ce76e4d75d24ba0f7d69cf4be530baa3a3ac15..dd22c08a7ebbe55b76c2d0e7b60bc7d21bf7ac1d 100644 (file)
@@ -381,7 +381,7 @@ file_chooser_widget_selection_changed (GtkWidget            *widget,
 {
   GtkFileChooserDialogPrivate *priv = gtk_file_chooser_dialog_get_instance_private (dialog);
   GtkWidget *button;
-  GSList *files;
+  GListModel *files;
   gboolean sensitive;
 
   button = get_accept_action_widget (GTK_DIALOG (dialog), FALSE);
@@ -389,10 +389,10 @@ file_chooser_widget_selection_changed (GtkWidget            *widget,
     return;
 
   files = gtk_file_chooser_get_files (GTK_FILE_CHOOSER (priv->widget));
-  sensitive = (files != NULL);
+  sensitive = (g_list_model_get_n_items (files) > 0);
   gtk_widget_set_sensitive (button, sensitive);
 
-  g_slist_free_full (files, g_object_unref);
+  g_object_unref (files);
 }
 
 static void
index 4eb46e4a4e31f23ed504b223e69021551ab08a64..d4c6563d25bc8bdbf045df1818062c039e072929 100644 (file)
@@ -683,7 +683,7 @@ gtk_file_chooser_native_set_current_name (GtkFileChooser    *chooser,
   g_clear_object (&self->current_file);
 }
 
-static GSList *
+static GListModel *
 gtk_file_chooser_native_get_files (GtkFileChooser *chooser)
 {
   GtkFileChooserNative *self = GTK_FILE_CHOOSER_NATIVE (chooser);
@@ -693,7 +693,16 @@ gtk_file_chooser_native_get_files (GtkFileChooser *chooser)
     case MODE_PORTAL:
     case MODE_WIN32:
     case MODE_QUARTZ:
-      return g_slist_copy_deep (self->custom_files, (GCopyFunc)g_object_ref, NULL);
+      {
+        GListStore *store;
+        GSList *l;
+
+        store = g_list_store_new (G_TYPE_FILE);
+        for (l = self->custom_files; l; l = l->next)
+          g_list_store_append (store, l->data);
+
+        return G_LIST_MODEL (store);
+      }
 
     case MODE_FALLBACK:
     default:
index a88fe367f7dbae584c16e62927657ba5658b28d4..092d785eb9e444bb8a4e4a04e520f5c30b9b21c1 100644 (file)
@@ -72,7 +72,7 @@ struct _GtkFileChooserIface
                                             GFile             *file);
   void           (*select_all)             (GtkFileChooser    *chooser);
   void           (*unselect_all)           (GtkFileChooser    *chooser);
-  GSList *       (*get_files)              (GtkFileChooser    *chooser);
+  GListModel *   (*get_files)              (GtkFileChooser    *chooser);
   GtkFileSystem *(*get_file_system)        (GtkFileChooser    *chooser);
   void           (*add_filter)             (GtkFileChooser    *chooser,
                                             GtkFileFilter     *filter);
index d41d9513cb953f1417b437f624372bbb934f76de..d05585c2996fc8322d0c524b807112b0fe2ed60c 100644 (file)
@@ -39,7 +39,7 @@ static void           delegate_unselect_file          (GtkFileChooser    *choose
                                                       GFile             *file);
 static void           delegate_select_all             (GtkFileChooser    *chooser);
 static void           delegate_unselect_all           (GtkFileChooser    *chooser);
-static GSList *       delegate_get_files              (GtkFileChooser    *chooser);
+static GListModel *   delegate_get_files              (GtkFileChooser    *chooser);
 static GtkFileSystem *delegate_get_file_system        (GtkFileChooser    *chooser);
 static void           delegate_add_filter             (GtkFileChooser    *chooser,
                                                       GtkFileFilter     *filter);
@@ -221,7 +221,7 @@ delegate_unselect_all (GtkFileChooser *chooser)
   gtk_file_chooser_unselect_all (get_delegate (chooser));
 }
 
-static GSList *
+static GListModel *
 delegate_get_files (GtkFileChooser *chooser)
 {
   return gtk_file_chooser_get_files (get_delegate (chooser));
index 3551463c23843f8a820a2ee81f6563781a042012..9a6f3b31fe63b7d4a93d4ebc4f812ef21bf06a02 100644 (file)
@@ -479,7 +479,7 @@ static void           gtk_file_chooser_widget_unselect_file                (GtkF
                                                                             GFile             *file);
 static void           gtk_file_chooser_widget_select_all                   (GtkFileChooser    *chooser);
 static void           gtk_file_chooser_widget_unselect_all                 (GtkFileChooser    *chooser);
-static GSList *       gtk_file_chooser_widget_get_files                    (GtkFileChooser    *chooser);
+static GListModel *   gtk_file_chooser_widget_get_files                    (GtkFileChooser    *chooser);
 static GtkFileSystem *gtk_file_chooser_widget_get_file_system              (GtkFileChooser    *chooser);
 static void           gtk_file_chooser_widget_add_filter                   (GtkFileChooser    *chooser,
                                                                             GtkFileFilter     *filter);
@@ -5408,7 +5408,7 @@ check_save_entry (GtkFileChooserWidget  *impl,
 
 struct get_files_closure {
   GtkFileChooserWidget *impl;
-  GSList *result;
+  GListStore *result;
   GFile *file_from_entry;
 };
 
@@ -5425,10 +5425,25 @@ get_files_foreach (GtkTreeModel *model,
   file = _gtk_file_system_model_get_file (fs_model, iter);
 
   if (!info->file_from_entry || !g_file_equal (info->file_from_entry, file))
-    info->result = g_slist_prepend (info->result, g_object_ref (file));
+    g_list_store_append (info->result, file);
 }
 
-static GSList *
+static GListModel *
+get_selected_files_as_model (GtkFileChooserWidget *impl)
+{
+  GListStore *store;
+  GSList *files, *l;
+
+  store = g_list_store_new (G_TYPE_FILE);
+  files = get_selected_files (impl);
+  for (l = files; l; l = l->next)
+    g_list_store_append (store, l->data);
+  g_slist_free_full (files, g_object_unref);
+
+  return G_LIST_MODEL (store);
+}
+
+static GListModel *
 gtk_file_chooser_widget_get_files (GtkFileChooser *chooser)
 {
   GtkFileChooserWidget *impl = GTK_FILE_CHOOSER_WIDGET (chooser);
@@ -5437,12 +5452,8 @@ gtk_file_chooser_widget_get_files (GtkFileChooser *chooser)
   GtkWidget *current_focus;
   gboolean file_list_seen;
 
-  info.impl = impl;
-  info.result = NULL;
-  info.file_from_entry = NULL;
-
   if (impl->operation_mode == OPERATION_MODE_SEARCH)
-    return get_selected_files (impl);
+    return get_selected_files_as_model (impl);
 
   if (impl->operation_mode == OPERATION_MODE_RECENT)
     {
@@ -5452,9 +5463,13 @@ gtk_file_chooser_widget_get_files (GtkFileChooser *chooser)
           goto file_entry;
         }
       else
-        return get_selected_files (impl);
+        return get_selected_files_as_model (impl);
     }
 
+  info.impl = impl;
+  info.result = g_list_store_new (G_TYPE_FILE);
+  info.file_from_entry = NULL;
+
   toplevel = get_toplevel (GTK_WIDGET (impl));
   if (toplevel)
     current_focus = gtk_root_get_focus (GTK_ROOT (toplevel));
@@ -5498,7 +5513,7 @@ gtk_file_chooser_widget_get_files (GtkFileChooser *chooser)
         return NULL;
 
       if (info.file_from_entry)
-        info.result = g_slist_prepend (info.result, info.file_from_entry);
+        g_list_store_append (info.result, info.file_from_entry);
       else if (!file_list_seen)
         goto file_list;
       else
@@ -5530,10 +5545,10 @@ gtk_file_chooser_widget_get_files (GtkFileChooser *chooser)
       current_folder = gtk_file_chooser_get_current_folder (chooser);
 
       if (current_folder)
-        info.result = g_slist_prepend (info.result, current_folder);
+        g_list_store_append (info.result, current_folder);
     }
 
-  return g_slist_reverse (info.result);
+  return G_LIST_MODEL (info.result);
 }
 
 static GtkFileSystem *
@@ -6143,18 +6158,18 @@ location_popup_on_paste_handler (GtkFileChooserWidget *impl)
 static void
 add_selection_to_recent_list (GtkFileChooserWidget *impl)
 {
-  GSList *files;
-  GSList *l;
+  GListModel *files;
+  guint i, n;
 
   files = gtk_file_chooser_widget_get_files (GTK_FILE_CHOOSER (impl));
 
-
   if (!impl->recent_manager)
     impl->recent_manager = gtk_recent_manager_get_default ();
 
-  for (l = files; l; l = l->next)
+  n = g_list_model_get_n_items (files);
+  for (i = 0; i < n; i++)
     {
-      GFile *file = l->data;
+      GFile *file = g_list_model_get_item (files, i);
       char *uri;
 
       uri = g_file_get_uri (file);
@@ -6163,9 +6178,11 @@ add_selection_to_recent_list (GtkFileChooserWidget *impl)
           gtk_recent_manager_add_item (impl->recent_manager, uri);
           g_free (uri);
         }
+
+      g_object_unref (file);
     }
 
-  g_slist_free_full (files, g_object_unref);
+  g_object_unref (files);
 }
 
 static gboolean
index eace90337c3a2ead2f886a2075cfaea8c325a835..d5eef8aedade4a270e72893c7ac95489718799df 100644 (file)
@@ -63,19 +63,21 @@ print_current_folder (GtkFileChooser *chooser)
 static void
 print_selected (GtkFileChooser *chooser)
 {
-  GSList *uris = gtk_file_chooser_get_files (chooser);
-  GSList *tmp_list;
+  GListModel *files = gtk_file_chooser_get_files (chooser);
+  guint i, n;
 
   g_print ("Selection changed :\n");
-  for (tmp_list = uris; tmp_list; tmp_list = tmp_list->next)
+  n = g_list_model_get_n_items (files);
+  for (i = 0; i < n; i++)
     {
-      GFile *file = tmp_list->data;
+      GFile *file = g_list_model_get_item (files, i);
       char *uri = g_file_get_uri (file);
       g_print ("  %s\n", uri ? uri : "(null)");
       g_free (uri);
+      g_object_unref (files);
     }
   g_print ("\n");
-  g_slist_free_full (uris, g_object_unref);
+  g_object_unref (files);
 }
 
 static void
@@ -87,28 +89,23 @@ response_cb (GtkDialog *dialog,
 
   if (response_id == GTK_RESPONSE_OK)
     {
-      GSList *list;
-
-      list = gtk_file_chooser_get_files (GTK_FILE_CHOOSER (dialog));
-
-      if (list)
-       {
-         GSList *l;
-
-         g_print ("Selected files:\n");
-
-         for (l = list; l; l = l->next)
-           {
-              GFile *file = l->data;
-              char *uri = g_file_get_uri (file);
-             g_print ("  %s\n", uri ? uri : "(null)");
-             g_free (uri);
-           }
+      GListModel *files;
+      guint i, n;
+
+      files = gtk_file_chooser_get_files (GTK_FILE_CHOOSER (dialog));
+      n = g_list_model_get_n_items (files);
+
+      g_print ("Selected files:\n");
+      for (i = 0; i < n; i++)
+        {
+          GFile *file = g_list_model_get_item (files, i);
+          char *uri = g_file_get_uri (file);
+          g_print ("  %s\n", uri ? uri : "(null)");
+          g_free (uri);
+          g_object_unref (file);
+        }
 
-         g_slist_free_full (list, g_object_unref);
-       }
-      else
-       g_print ("No selected files\n");
+      g_object_unref (files);
     }
   else
     g_print ("Dialog was closed\n");
@@ -208,33 +205,24 @@ static void
 get_selection_cb (GtkButton      *button,
                  GtkFileChooser *chooser)
 {
-  GSList *selection;
+  GListModel *selection;
+  guint i, n;
 
   selection = gtk_file_chooser_get_files (chooser);
+  n = g_list_model_get_n_items (selection);
 
   g_print ("Selection: ");
 
-  if (selection == NULL)
-    g_print ("empty\n");
-  else
+  for (i = 0; i < n; i++)
     {
-      GSList *l;
-      
-      for (l = selection; l; l = l->next)
-       {
-          GFile *file = l->data;
-         char *uri = g_file_get_uri (file);
-
-         g_print ("%s\n", uri);
-
-          g_free (uri);
-
-         if (l->next)
-           g_print ("           ");
-       }
+      GFile *file = g_list_model_get_item (selection, i);
+      char *uri = g_file_get_uri (file);
+      g_print ("%s\n", uri);
+      g_free (uri);
+      g_object_unref (file);
     }
 
-  g_slist_free_full (selection, g_object_unref);
+  g_object_unref (selection);
 }
 
 static void
index 50db5c8111743e406e929a561f6ff17b7b7d532e..acb14b7615218d154c3b756bd3a5d56c122d8821 100644 (file)
@@ -5507,22 +5507,26 @@ native_response (GtkNativeDialog *self,
 {
   static int count = 0;
   char *res;
-  GSList *uris, *l;
   GString *s;
   char *response;
   GtkFileFilter *filter;
+  GListModel *files;
+  guint i, n;
 
-  uris = gtk_file_chooser_get_files (GTK_FILE_CHOOSER (self));
+  files = gtk_file_chooser_get_files (GTK_FILE_CHOOSER (self));
   filter = gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (self));
   s = g_string_new ("");
-  for (l = uris; l != NULL; l = l->next)
+  n = g_list_model_get_n_items (files);
+  for (i = 0; i < n; i++)
     {
-      char *uri = g_file_get_uri (l->data);
+      GFile *file = g_list_model_get_item (files, i);
+      char *uri = g_file_get_uri (file);
       g_string_prepend (s, uri);
       g_string_prepend (s, "\n");
       g_free (uri);
+      g_object_unref (file);
     }
-  g_slist_free_full (uris, g_object_unref);
+  g_object_unref (files);
 
   switch (response_id)
     {